シェルスクリプト (bash)
バッチファイルです。一連のコマンドラインの入力を自動的に行います。
シェルを起動したときやログインしたときなどに自動的に実行されるスクリプト・ファイルがあります。
bash のフルネームは、Bourne Again Shell です。
関連
サンプル
#!/bin/bash -eEx
#// Content-Type: text/plain; charset=utf-8
#// -eE オプションは、エラーが起きたら中断します
#// -x オプションは、1行ずつコマンドを表示します
#// execute sample shell script
if [ -e ~/reset_env.sh ]; then source ~/reset_env.sh ;fi
export WORK="$HOME/work"
#//(end of export)
cd $WORK
if [ -e "$WORK/output" ]; then rm -r "$WORK/output" ;fi
echo created \"$WORK/output/sample\"
参考
改行が Windows 形式(CR+LF) になっていると動きません。
日本語を含むときは、文字コードセットを UTF-8 にして保存してください。
bash --version
bash のバージョンを確認する
arr=( a b )
`command param`
実行ファイルの起動、または、関数呼び出し
$arr
変数参照
${arr}
${arr[0]}
${#arr[@]}
$( command param )
実行ファイルの起動、または、関数呼び出し
command1 ; command2
; は、2つの文を1行にまとめるときの区切り
# comment
コメント
command1 \
param
行末の \ は、1つの文を複数行に分ける
$?
終了ステータス
"$1"
"$2"
実行ファイルの引数、関数の引数
$*
"$@"
"param 1"
" " で囲むと、空白、タブ、改行があっても、1つの引数にする
変数の値を参照する。エスケープ文字(\)が使える
' ' で囲むと、空白、タブ、改行があっても、1つの引数にする
$ があっても変数の値を参照しない
'param 1'
$(( $var + 1 ))
計算。 結果が 0 でも、終了コードは1になりません
関連
${aa["Attr1"]}
arr[0]="value"
aa["Attr1"]="value"
配列の要素への代入
command | pipe
command > pipe
リダイレクト
パイプ
ObjectA=( [Attr1]="Value1" [Attr2]="Value2" )
<( command param )
配列、または連想配列の要素数の参照
連想配列の要素への代入
の要素の参照
の要素の参照
の生成
の生成
サンプル・シェルスクリプト
#!/bin/bash
echo Hello World
テキスト・エディターで、スクリプトを記述します。
Linux では、スクリプトのファイルに、実行可能属性を付けます。
chmod 777 sample.sh
1行目は、スクリプトを解釈するプログラムを指定します。
2行目以降は、スクリプトの本体です。
sample.sh
カレント・ディレクトリにあるスクリプトを実行するときは、ピリオドとスラッシュに続けて、
ファイル名を入力してください。
./sample.sh
コマンド・プロンプトで
コマンド・プロンプトで
#! を、シェバング(shebang) と呼びます。
Mac では、Windows などからコピーしたファイルは、全てのファイルに、実行可能属性を付けています。
#!/bin/bash
set -e #// Do not continue, if error was raised
エラーが発生したら中断した方がいいので、次のように set -e を記述してください。
参考
どこでエラーが発生したか調べるときは、-x オプションを記述して実行してください。
実行しているコマンドを表示しながら実行します。
#!/bin/bash -x
参考
sample.sh
sample.sh
cp /dev/stdin ~/temporary.sh
ln -s /dev/console /dev/stdin
/dev/stdin が無いときの事前処理:
シェルから次のように入力します。
#!/bin/bash -xe
#// -x option echos commands
#// -e option does not continue, if error was raised
#// This is sample shell script
if [ -e ~/reset_env.sh ]; then source ~/reset_env.sh ;fi
export WORK="$HOME/work"
#//(end of export)
cd "$WORK"
./configure
make
内容を入力するモードになるので、スクリプトの内容をコピー&ペーストします。
最終行の改行をしてから、[Ctrl]+[C] を押すと、ファイルが作成されます。
if [ -e ~/sed_env.sh ]; then ~/sed_env.sh ~/temporary.sh ;fi
chmod 777 ~/temporary.sh
time ~/temporary.sh
シェルから次のように入力すると実行します。
ここで、sed_env.sh を作成すると、スクリプト内の環境変数の値を、自分の設定に変えることができます。
参考
シェルに入力する手順書を、一時的に実行するスクリプトにすると、作業効率が良くなります。
次の手順で、作業を行います。
(サンプル・スクリプト)
→ 環境変数の修正を自動化する (sed_env.sh)
sed_env.sh
sudo ln -s /proc/self/fd/0 /dev/stdin
または
/dev/stdin が使えないとき
samba 経由で編集する
vi で編集する
time は、コマンドの実行時間を表示するコマンドです。
#!/bin/bash -e
#// bash -x option echos commands
#// -e option does not continue, if error was raised
#// reset environment variables
out="$HOME/reset_env.sh" #// attention: can not replace to this variable in this file
not_modifies=( "PWD" "SSH_CLIENT" "SSH_CONNECTION" "XDG_SESSION_COOKIE" "SHLVL" )
read -p "Continue ? (If you want to exit, Ctrl+C) " key
#// make script
echo '#!/bin/bash' > $out
echo >> $out
echo "#// backup current folder" >> $out
echo 'current_folder=$PWD' >> $out
echo 'if [ "$current_folder" == "" ]; then unset ERROR;${ERROR:?PWD(current directory)Error} ;fi' >> $out
echo 'if [ ! -e "$current_folder" ]; then unset ERROR;${ERROR:?PWD(current directory)Error} ;fi' >> $out
echo >> $out
echo "#// clear all variables" >> $out
echo '`export | sed -e "s/^declare -x/unset/g" -e "s/=.*$//g" \' >> $out
for name in ${not_modifies[@]};do
echo "-e \"s/unset $name//\" \\" >> $out
done
echo ' ` #// ` is necessary' >> $out
echo >> $out
echo "#// set reset variables" >> $out
export >> $out
echo >> $out
echo "#// restore current folder" >> $out
echo 'cd "$current_folder"' >> $out
echo >> $out
echo 'echo export environment variables reseted.' >> $out
echo 'if [ "$SHLVL" == "2" ]; then echo "usage: source ~/reset_env.sh" ;fi' >> $out
for name in ${not_modifies[@]};do
sed -i.bak -e "s%declare -x $name=%#// declare -x $name=%" $out ; rm $out.bak
done
chmod 777 $out
echo "Created ~/reset_env.sh using current environment variables"
echo If you want to reset environment variables, type \"source \~/reset_env.sh\"
~/make_reset_env.sh
source ~/reset_env.sh
インストール
環境変数をリセットするスクリプト ~/reset_env.sh を作成するスクリプト ~/make_reset_env.sh
を、次のように作成します。
ログインしなおして、下記を実行すると、~/reset_env.sh ができます。
シェルから次のように入力すると、環境変数の内容がリセットされます。
cp /dev/stdin ~/make_reset_env.sh
chmod 777 ~/make_reset_env.sh
シェルから次のように入力します。
内容を入力するモードになるので、スクリプトの内容をコピー&ペーストします。
最終行の改行をしてから、[Ctrl]+[C] を押すと、ファイルが作成されます。
シェルから次のように入力します。
実行
← reset_env.sh にも対応
関連
if [ -e ~/reset_env.sh ]; then source ~/reset_env.sh ;fi
スクリプトに埋め込むときは、次のようにするとよいでしょう。
#!/bin/bash -e
#// -x option echos commands
#// -e option does not continue, if error was raised
#// delete folders, if user confirm get
w_DisableForceSudoInput=$w_DisableForceSudoInput
if [ -e ~/reset_env.sh ]; then source ~/reset_env.sh ;fi
#//===========================================================
#// [ Deleting Folders ]
export WORK="$HOME/work"
export w_SetupWork="$WORK/setup/setup_work"
export w_Work2Folder="$WORK/work2"
folders=( "$w_SetupWork" "$w_Work2Folder" )
#//===========================================================
#//=== list up paths of deleting folders
echo "---------------------------"
for (( i = 0; i < ${#folders[@]}; i ++ ));do
echo ${folders[$i]}
done
#//=== get user confirm
read -p "These folders delete (with sudo) ? (yes=y) >" key
if [ "$key" != "y" ]; then unset ERROR;${ERROR:?user exit} ;fi
#//=== force input sudo password
if [ "$w_DisableForceSudoInput" != "1" ]; then sudo -k ;fi
sudo echo This script run as super user
#//=== delete folders with sudo
for (( i = 0; i < ${#folders[@]}; i ++ ));do
echo "Deleting ${folders[$i]}"
if [ -e "${folders[$i]}" ]; then sudo rm -r "${folders[$i]}" ;fi
done
cp /dev/stdin ~/clean.sh
シェルから次のように入力します。
内容を入力するモードになるので、下記のスクリプトの内容をコピー&ペーストします。
ただし、[ Deleting Folders ] の部分を修正してください。
インストール
chmod 777 ~/clean.sh
最終行の改行をしてから、[Ctrl]+[C] を押すと、ファイルが作成されます。
最後に、シェルから次のように入力して、実行可能な状態にします。
$ ~/clean.sh
---------------------------
/home/user1/work/setup/setup_work
/home/user1/work/work2
These folders delete (with sudo) ? (yes=y) >y
Deleting /home/user1/work/setup/setup_work
Deleting /home/user1/work/work2
実行するときは、シェルから clean.sh を起動します。
実行する
#!/bin/bash
# filename
filename=$1
# extension
extension=${filename##*.}
# run python
if [ "$extension" = "py" ]; then
/usr/local/bin/python $HOME/script/$1
else
echo "file extension not match"
fi
cp /dev/stdin s
chmod 777 s
sudo cp s /usr/bin
rm s
ターミナルから、次のコマンドを入力します。
インストール
下記の内容をクリップボードにコピーして、ターミナルを右クリックして
貼り付けます。
ターミナルから、次のコマンドを入力します。
または cp s /usr/bin
/usr/local/bin/python $HOME/script/$1
py
/usr/bin
実行例
s script.py
s スクリプトのパラメーターにファイル名を指定すると、そのファイル名の
拡張子を判定して、対応するプログラムを起動します。
/dev/console の場合もあります
最終行の改行を入力したら、Ctrl+C を押します。
source コマンドを使えば、スクリプトの中で途中で止めて、そこから任意のコマンドを入力する
ことができます。 環境変数なども設定された状態でコマンドを入力できます。
function Make_func()
{
local Target="$1"
PATH="$HOME/bin:$PATH"
cd "$HOME/work"
read -p "Continue ? (If you want to exit, Ctrl+C) " key #// 中断
make $Target
}
$ source ./sample.sh
Continue ? (If you want to exit, Ctrl+C) ^C
$ Target="sample"
$ make V=1 $Target
サンプル
sample.sh
上記のスクリプトの make $Target コマンドを実行するタイミングで任意のコマンドを入力
したいときは、上記のように make の前に入力待ちを作り、source コマンドを付けて、
sample.sh を実行し、[Ctrl]+[C] を押して、local 変数を設定すれば、任意のコマンドを入力
することができます。
$ cp /dev/stdin sample.sh
#!/bin/bash
echo Hello $1
^C
$ chmod 777 sample.sh
$ ./sample.sh World
Hello World
$ echo $?
1
プログラムの main 関数の返り値は、終了コードになります。
通常 0 は、エラーなしです。
終了コードは、$? に格納されます。
変数の番号をずらすには、shift コマンドを使います。
パラメーターは、シフトする数です。 省略すると 1 です。
$ cp /dev/stdin sample.sh
#!/bin/bash
echo $1 $2
shift
echo $1 $2
^C
$ chmod 777 sample.sh
$ ./sample.sh A B
A B
B
シェルから入力してください
サンプル
#!/bin/bash
echo Hello $1
sample.sh
パラメーターを参照する部分に、$1, $2 を記述してください。
シェルから入力してください
サンプル
を動かしています
シェルから入力してください
サンプル
$ cp /dev/stdin sample.sh
#!/bin/bash
while [ "$1" != "" ] ; do
echo $1
shift
done
^C
$ chmod 777 sample.sh
$ ./sample.sh A B
A
B
#!/bin/bash
while [ "$1" != "" ] ; do
echo $1
shift
done
sample.sh
を動かしています
$# は、パラメーターの個数になります。
すべてのパラメーターを一覧するときは、$* または $@ を記述してください。
#!/bin/bash -x
echo $*
echo $@
echo "$*"
echo "$@"
$ ~/temporary.sh A B
+ echo A B
A B
+ echo A B
A B
+ echo 'A B'
A B
+ echo A B
A B
temporary.sh
実行結果
$ read -p "prompt> " VAR
prompt> foo
$ echo $VAR
foo
read コマンドは、ユーザーから入力を要求して、その内容をシェル変数に格納します。
-p オプションで、プロンプトを表示します。
read -p "These folders delete ? (yes=y) >" key
if [ "$key" != "y" ]; then unset ERROR;${ERROR:?user exit} ;fi
サンプル
削除の確認をする
read -p "Continue ? (If you want to exit, Ctrl+C) " key
続きを実行するか確認する
サンプル
続きを実行するか確認する。 タイムアウト 30秒
read -p "Continue ? (If you want to exit, Ctrl+C) " -t 30 key
サンプル
関連
local line
cat "file.txt" | while read line ; do #//[out] line
echo "$line"
done ; done_func $?
パイプの後は、サブシェルになるため、上記のループの中で環境変数に設定した内容は、
ループの外には反映されません。
参考
local line
#// read lines one by one from redirect "<" after this loop
while read line ; do #// このループの後のリダイレクト"<" から1行ずつリードします
echo "$line"
done < <( cat "file.txt" ) ; done_func $?
line
cat "file.txt"
<( ... ) は、Process Substitution です。
# comment
# 文字から行末までは、コメントとして、何も実行しません。
行の途中からコメントにすることもできます。
export VAR=abc # comment
if [ 条件文@ ]; then
処理@
elif [ 条件文A ]
処理A
else
処理B
fi
case 値 in
比較値@)
処理@
;;
比較値A)
処理AA
処理AB
;;
*)
処理B
;;
esac
条件文@が真(満たしたとき)なら、
処理@を実行します。
そうでないとき、条件文Aが真なら、
処理Aを実行します。
それ以外のとき、
処理Bを実行します。
値が、
比較値@と等しいなら、
処理@を実行します。
値が比較値Aと等しいなら、
処理Aと処理ABを実行します。
値がその他の値なら、
処理Bを実行します。
if [ 条件文@ ]; then 処理@ ;fi
#!/bin/bash
case $1 in
.C) echo "match .C";;
?C) echo "match ?C";;
*C) echo "match *C";;
A[BC]D) echo "match A[BC]D";;
A[!BE]D) echo "match A[!BE]D";;
$2) echo 'match $2';;
*) echo "not match";;
esac
$ ~/temporary.sh AC
match ?C
$ ~/temporary.sh ABC
match *C
$ ~/temporary.sh ACD
match A[BC]D
$ ~/temporary.sh ADD
match A[!BE]D
$ ~/temporary.sh AED
not match
$ ~/temporary.sh AED AED
match $2
case の比較値には、ワイルドカードも使えます。 正規表現ではありません。
temporary.sh
実行結果
case $VAR in *ERROR*) echo "Error"; esac
$VAR に ERROR があるとき
case $VAR in *$KEY*) echo "Key"; esac
$VAR の値に $KEY の値があるとき
case $VAR in *ERROR*);; *) echo "Error"; esac
$VAR に ERROR がないとき
if [ 条件文@ ]; then 処理@ ;else 処理B ;fi
[ 〜 ] の [ は、コマンド名です。 [ 〜 ] は、test 〜 と同じです。
if true; then
true は、終了ステータスが 0 になるコマンドです。
if 〜 then は、終了ステータスが 0 なら真と判定します。
if ! false; then
false は、終了ステータスが 1 になるコマンドです。
if ! 〜 then は、終了ステータスが 0 以外なら真と判定します。
case の比較値には、| を使って複数指定できます。
case "$var" in
"a" | "b")
処理@
;;
esac